
;(function(window){

	var Vertex = function(label){
		return {
			label: label,
			wasVisited: false
		};
	};


	var GraphN = function(){
		this._MAX_VERTS = 20;
		this._vertexList = []; // 存储顶点的数组
		this._adjMat = []; // 邻接矩阵（二维数组）
		this._vtxLn = 0;

		for( var i=0;i<this._MAX_VERTS;i++){
			this._adjMat[i] = [];
			for( var j=0;j<this._MAX_VERTS;j++)
				this._adjMat[i][j] = 0;
		}
	};
	GraphN.prototype={
		constructor: GraphN,
		addVertex: function(label){
			this._vertexList[this._vtxLn++] = Vertex(label);
		},
		addEdge: function(start, end){
			this._adjMat[start][end] = 1;
			this._adjMat[end][start] = 1;
		},
		_getAdjUnvisitedVertex: function(v){
			for( var j=0;j<this._vtxLn; j++)
				if( this._adjMat[v][j] == 1 && this._vertexList[j].wasVisited == false)
					return j;
			return -1;
		},
		/**
		 * 深度优先搜索
		 * Deep First Search
		 * @param onAccessVtx
		 */
		dfs: function(onAccessVtx){
			var stack = new Stack(this._MAX_VERTS);
			this._vertexList[0].wasVisited = true;
			onAccessVtx(this._vertexList[0]);
			stack.push(0);
			while(!stack.isEmpty()){
				var v = this._getAdjUnvisitedVertex(stack.peek());
				if( v == -1){
					stack.pop();
				}else{
					this._vertexList[v].wasVisited = true;
					onAccessVtx(this._vertexList[v]);
					stack.push(v);
				}
			}
			for(var j=0;j<this._vtxLn;j++)
				this._vertexList[j].wasVisited = false;
		},
		/**
		 * 广度优先搜索
		 * Breadth First Search
		 * @param onAccessVtx
		 */
		bfs: function(onAccessVtx){
			var queue = new Queue(this._MAX_VERTS);
			this._vertexList[0].wasVisited = true;
			onAccessVtx(this._vertexList[0]);
			queue.enque(0);
			var v2;
			while(!queue.isEmpty()){
				var v1 = queue.deque();
				while((v2 = this._getAdjUnvisitedVertex(v1))!=-1){
					this._vertexList[v2].wasVisited = true;
					onAccessVtx(this._vertexList[v2]);
					queue.enque(v2);
				}
			}
			for(var j=0;j<this._vtxLn;j++)
				this._vertexList[j].wasVisited = false;
		}
	};

	window.GraphN = GraphN;
})(window);